package com.wlyuan.open.scanner.repository.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wlyuan.open.scanner.application.factory.SyncFactory;
import com.wlyuan.open.scanner.assembler.ScannerUserAssembler;
import com.wlyuan.open.scanner.constant.Constants;
import com.wlyuan.open.scanner.dao.entity.UserDO;
import com.wlyuan.open.scanner.dao.mapper.UserMapper;
import com.wlyuan.open.scanner.domain.user.User;
import com.wlyuan.open.scanner.domain.user.UserConvert;
import com.wlyuan.open.scanner.repository.UserRepository;
import com.wlyuan.open.scanner.utils.StreamUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

/**
 * @author lijing
 * @description
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class UserRepositoryImpl implements UserRepository {
    private final UserMapper userMapper;
    private final SyncFactory syncFactory;

    @Override
    public List<User> list() {
        logger.info("公司ID > 0 and roleId <> 2048 and roleId <> 256 and roleId > 0");
        List<UserDO> list = userMapper.list();
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        logger.info("老数据数据量，size：{}", list.size());
        var result = UserConvert.convert(list);
        result.forEach(u -> process(u));
        return result;
    }

    @Override
    public User getById(Long userId) {
        return Optional.ofNullable(userId).map(id -> {
            var user = userMapper.selectById(id);
            var result = UserConvert.convert(user);
            process(result);
            return result;
        }).orElse(null);
    }

    @Override
    public List<Long> getByTime(String startTime, String endTime) {
        return userMapper.getByTime(startTime, endTime);
    }

    @Override
    public List<Long> getByTenantIdTime(Long tenantId, String startTime, String endTime) {
        return userMapper.getByTenantIdTime(tenantId, startTime, endTime);
    }

    @Override
    public Long getUserTenant(Long userId) {
        return Optional.ofNullable(userId).map(id -> {
            return Optional.ofNullable(userMapper.selectById(id)).map(UserDO::getUserCompanyid).orElse(null);
        }).orElse(null);
    }

    @Override
    public void getByTenantId(Long tenantId) {
        Optional.ofNullable(tenantId).ifPresent(tenant -> {
            LambdaQueryWrapper<UserDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserDO::getUserCompanyid, tenant);
            var list = userMapper.selectList(queryWrapper);
            if (CollectionUtils.isEmpty(list)) {
                return;
            }
            list.forEach(user -> {
                var result = UserConvert.convert(user);
                process(result);
                syncFactory.sync(ScannerUserAssembler.assemble(result));
            });
        });
    }

    @Override
    public List<User> getAdminUser() {
        //获取管理员账号信息：User_RoleID = 256 and tu.User_Invalid = 0 and user_name is not null, 根据tu.User_CompanyID 分组 取user_signInTime 最新的
        LambdaQueryWrapper<UserDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDO::getUserRoleid, Constants.ADMIN_ROLE_ID).eq(UserDO::getUserInvalid, Constants.INVALID_NUMBER_ZERO).isNotNull(UserDO::getUserName);
        List<UserDO> list = userMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        //根据User_CompanyID 分组 取UserSignintime 时间最大的
        var result = StreamUtils.maxByGroupValues(list, UserDO::getUserCompanyid, Comparator.comparing(UserDO::getUserSignintime, Comparator.nullsFirst(Comparator.naturalOrder())));
        return UserConvert.convert(result);
    }

    private void process(User user) {
        if (!Optional.ofNullable(user).isPresent()) {
            return;
        }
        if (StringUtils.isBlank(user.getName())) {
            user.setName(user.getAccount());
        }
    }
}
